package com.afdor.rws;

import org.apache.commons.lang3.RandomStringUtils;

import java.util.Objects;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * 测试volatile关键字在多线程下的一些问题
 *
 * @author 悭梵
 * @date Created in 2018-09-17 17:01
 */
public class TestVolatile {

    /**
     * 消费者线程池
     */
    protected static final ScheduledThreadPoolExecutor THREAD_POOL = new ScheduledThreadPoolExecutor(10);

    public static void main(String[] args) {
        Test1 test1 = new Test1();
        for (int i = 0; i < 100; i++) {
            THREAD_POOL.submit(new Runnable() {
                @Override
                public void run() {
                    test1.sKey = RandomStringUtils.randomAlphanumeric(100, 120);
                    test1.setObjects(new String[]{test1.sKey});
                }
            });
            THREAD_POOL.submit(new Runnable() {
                @Override
                public void run() {
                    StringBuilder builder = new StringBuilder(200);
                    builder.append("------------------------------------------------------------------------------------\n");
                    builder.append("--").append(Objects.equals(test1.sKey, test1.objects[0])).append(", sKey=").append(test1.sKey).append(", mapKey=").append(test1.objects[0]).append("\n");
                    System.out.println(builder);
                }
            });
        }
        LockSupport.parkNanos(TimeUnit.MINUTES.toNanos(1));
        THREAD_POOL.shutdown();
    }

}

/**
 * <ul>
 * <li>可见性：对一个volatile变量的读，总是能看到（任意线程）对这个volatile变量最后的写入</li>
 * <li>原子性：对任意单个volatile变量的读/写具有原子性(long,double这2个8字节的除外)，但类似于volatile++这种复合操作不具有原子性。</li>
 * <li> volatile修饰的变量如果是对象或数组之类的，其含义是对象获数组的地址具有可见性，但是数组或对象内部的成员改变不具备可见性</li>
 * </ul>
 */
class Test1 {
    volatile String sKey = "11111111111111111";
    volatile Object[] objects;

    public void setObjects(Object[] objects) {
        this.objects = objects;
    }
}
